//*********************************************************
//
//    Copyright (c) Microsoft. All rights reserved.
//    This code is licensed under the Apache License, Version 2.0.
//    THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
//    ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
//    IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
//    PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//*********************************************************

namespace Microsoft.Research.ScientificWorkflow.UIDesigner
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Workflow.Activities;
    using System.Workflow.ComponentModel;
    using Microsoft.Research.ScientificWorkflow.TridentModel;
    using System.Windows.Controls;
    using System.Collections.ObjectModel;

    /// <summary>
    /// Holds the Condition Connector Temp data for IfElse 
    /// </summary>
    public class ConditionDataStore
    {
        /// <summary>
        /// Holds the Collection of Logical Opeartors for each IFConditionConnector in the Composer
        /// </summary>
        private Dictionary<string, Collection<LogicalOperatorActivityBody>> conditionDictionary = null;

        /// <summary>
        /// Holds the List of Condition Connectors in the Composer
        /// </summary>
        private Collection<ConditionConnector> conditionConnectorList = new Collection<ConditionConnector>();

        /// <summary>
        ///Constructor 
        /// </summary>
        public ConditionDataStore()
        {
            this.conditionDictionary = new Dictionary<string, Collection<LogicalOperatorActivityBody>>();
        }

        /// <summary>
        /// Adds the Logical Operator to the Collection<LogicalOperatorActivityBody> in conditionDictionary
        /// </summary>
        /// <param name="conditionActivityId"></param>
        /// <param name="sequenceActivity"></param>
        public void AddConditionOperator(string conditionActivityId, LogicalOperatorActivityBody sequenceActivity)
        {
            Collection<LogicalOperatorActivityBody> conditionalOperatorList;

            // Get the Collection<LogicalOperatorActivityBody> from the conditionDictionary
            this.conditionDictionary.TryGetValue(conditionActivityId, out conditionalOperatorList);
            if (null == conditionalOperatorList)
            {
                // If no Logical Opeartor has been added initialize and add the Operator to the Collection
                conditionalOperatorList = new Collection<LogicalOperatorActivityBody>();
                conditionDictionary.Add(conditionActivityId, conditionalOperatorList);
            }

            if (null != conditionalOperatorList)
            {
                //Adds the LogicalOperator to the Collection
                conditionalOperatorList.Add(sequenceActivity);
            }
        }

        /// <summary>
        /// Clears the conditionDictionary
        /// </summary>
        public void ClearConditionalDictionary()
        {
            this.conditionDictionary.Clear();
        }

        /// <summary>
        /// Adds the Condition Connector to the Collection
        /// </summary>
        /// <param name="connector"></param>
        public void AddConditionalConnector(ConditionConnector connector)
        {
            // Check whether the Condition Connector present in the List
            ConditionConnector connectorExistInList = this.conditionConnectorList.FirstOrDefault(checkCondition => checkCondition.ConditionActivity.UniqueId.Equals(connector.ConditionActivity.UniqueId));
            // Add if the List is not having the Connector
            if (connectorExistInList == null)
            {
                this.conditionConnectorList.Add(connector);
            }
        }

        /// <summary>
        /// Clears the Condition Connector List
        /// </summary>
        public void ClearConditionalConnectorList()
        {
            this.conditionConnectorList.Clear();
        }

        /// <summary>
        /// Clears the Dictionary and conditionConnectorList
        /// </summary>
        public void ClearDataStore()
        {
            this.conditionDictionary.Clear();
            this.conditionConnectorList.Clear();
        }

        /// <summary>
        /// Remove the Condition Connector and corresponding Distionary Entries from the Data Store
        /// </summary>
        /// <param name="connectorId"></param>
        public void RemoveFromConditionalConnectorList(string connectorId)
        {
            ConditionConnector result = null;
            foreach (ConditionConnector connector in this.conditionConnectorList)
            {
                if (connector.ConditionActivity.UniqueId.Equals(connectorId, StringComparison.CurrentCulture))
                {
                    result = connector;
                    break;
                }
            }
            if (result != null)
            {
                if (conditionDictionary != null)
                {
                    // Remove the Condition from the Dictionary 
                    conditionDictionary.Remove(connectorId);
                }

                this.conditionConnectorList.Remove(result);
            }
        }

        /// <summary>
        /// Remove the Logical Operator from the  Collection<LogicalOperatorActivityBody>
        /// </summary>
        /// <param name="conditionId">Condition Connector Id</param>
        /// <param name="logicalOperator">Logical Opearator which need to remove</param>
        public void RemoveLogicalOperator(string conditionId, LogicalOperatorActivityBody logicalOperator)
        {
            Collection<LogicalOperatorActivityBody> conditionalOperatorList = GetConditionList(conditionId);
            conditionalOperatorList.Remove(logicalOperator);
        }

        /// <summary>
        /// Get the Logical Operator List for the given Condition Connector Id
        /// </summary>
        /// <param name="conditionActivityId">Condition Connector Id</param>
        /// <returns>Collection<LogicalOperatorActivityBody></returns>
        public Collection<LogicalOperatorActivityBody> GetConditionList(string conditionActivityId)
        {
            Collection<LogicalOperatorActivityBody> conditionalOperatorList;
            conditionDictionary.TryGetValue(conditionActivityId, out conditionalOperatorList);

            if (null == conditionalOperatorList)
            {
                conditionalOperatorList = new Collection<LogicalOperatorActivityBody>();
            }
            return conditionalOperatorList;
        }

        /// <summary>
        /// Get Collection of ConditionConnector
        /// </summary>
        /// <returns> Collection<ConditionConnector></returns>
        public Collection<ConditionConnector> FetchConditionalConnectorList()
        {
            return this.conditionConnectorList;
        }

        /// <summary>
        /// Get the Condition Connector for given Connector name
        /// </summary>
        /// <param name="connectorName">Connector name</param>
        /// <returns>ConditionConnector</returns>
        public ConditionConnector GetConditionalConnector(string connectorName)
        {
            foreach (ConditionConnector connector in this.conditionConnectorList)
            {
                if (connector.ConditionActivity.UniqueId.Equals(connectorName))
                {
                    return connector;
                }
            }
            return null;
        }

        /// <summary>
        /// Get the activity Model for the passed Id
        /// </summary>
        /// <param name="ifElseName">Condition Connector name</param>
        /// <param name="activityModelName">activityModelName</param>
        /// <returns>SimpleActivityModel</returns>
        public SimpleActivityModel GetActivityModel(string ifElseName, string activityModelName)
        {
            if (conditionDictionary.ContainsKey(ifElseName))
            {
                Collection<LogicalOperatorActivityBody> activityList = conditionDictionary[ifElseName];
                foreach (LogicalOperatorActivityBody body in activityList)
                {
                    if (body.Model.UniqueId.Equals(activityModelName, StringComparison.CurrentCultureIgnoreCase))
                    {
                        return body.Model as SimpleActivityModel;
                    }
                }

                return null;
            }
            else
            {
                return null;
            }

        }

        /// <summary>
        /// Get the LogicalOperatorActivityBody
        /// </summary>
        /// <param name="conditionActivityId">conditionActivityId</param>
        /// <param name="model">SimpleActivityModel</param>
        /// <returns>LogicalOperatorActivityBody</returns>
        public LogicalOperatorActivityBody GetActivityBody(string conditionActivityId, SimpleActivityModel model)
        {
            if (conditionDictionary.ContainsKey(conditionActivityId))
            {
                Collection<LogicalOperatorActivityBody> activityList = conditionDictionary[conditionActivityId];
                foreach (LogicalOperatorActivityBody body in activityList)
                {
                    if (body.Model == model)
                    {
                        return body;
                    }
                }

                return null;
            }

            return null;
        }

        /// <summary>
        /// Removes the Activity Body from the condition connector 
        /// </summary>
        /// <param name="conditionActivityId">conditionActivityId</param>
        /// <param name="model">SimpleActivityModel</param>
        public void RemoveActivityBody(string conditionActivityId, SimpleActivityModel model)
        {
            if (conditionDictionary.ContainsKey(conditionActivityId))
            {
                Collection<LogicalOperatorActivityBody> activityList = conditionDictionary[conditionActivityId];
                LogicalOperatorActivityBody requiredBody = this.GetActivityBody(conditionActivityId, model);
                if (requiredBody != null)
                {
                    activityList.Remove(requiredBody);
                    Panel parent = requiredBody.Parent as Panel;
                    if (parent != null)
                    {
                        parent.Children.Remove(requiredBody);
                    }
                }
            }
        }
    }
}